package com.tiancheng.trade.payment.channel.umsdhjt;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tiancheng.trade.commom.core.data.Result;
import com.tiancheng.trade.commom.core.exception.error.BusinessErrorInfoEnum;
import com.tiancheng.trade.commom.core.utils.JsonUtil;
import com.tiancheng.trade.commom.core.utils.ForestHttpUtil;
import com.tiancheng.trade.commom.web.http.PlatformRequest;
import com.tiancheng.trade.payment.channel.bo.RefundOrderBO;
import com.tiancheng.trade.payment.channel.bo.RefundOrderResBO;
import com.tiancheng.trade.payment.channel.enums.UmsErrCodeEnum;
import com.tiancheng.trade.payment.channel.ums.params.UmsRefundOrderParam;
import com.tiancheng.trade.payment.channel.ums.params.UmsRefundOrderResult;
import com.tiancheng.trade.payment.channel.umsdhjt.request.UmsDhjtRefundOrderParam;
import com.tiancheng.trade.payment.channel.umsdhjt.request.UmsDhjtSettleNotifyRequest;
import com.tiancheng.trade.payment.mapper.PaymentRefundFlowMapper;
import com.tiancheng.trade.payment.model.PaymentRefundFlow;
import com.tiancheng.trade.payment.service.PaymentRefundFlowDetailService;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.message.BasicHeader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Map;

import static com.tiancheng.trade.payment.channel.ums.utils.UmsUtil.buildSignString;

@Component
@Slf4j
public class UmsDhjtAsyncComponent {
    @Resource
    private PlatformRequest platformRequest;
    @Autowired
    private PaymentRefundFlowMapper paymentRefundFlowMapper;
    @Autowired
    private PaymentRefundFlowDetailService refundFlowDetailService;
    // 退款超商户当日限额
    public static final String DAYMAXREFUNDAMOUNT_OVER="DAYMAXREFUNDAMOUNT_OVER";

    /**
     * 2022-07-22 银联反馈不限制子订单部分退款，测试用
     * 一次退款，测试
     * @param umsRefundOrderParam 退款参数
     * @return
     */
    public Result<RefundOrderResBO> refundWithSubOrders(UmsDhjtRefundOrderParam umsRefundOrderParam, RefundOrderBO refundOrderBO,
                                                        Map<String, String> subMerchantMap, Map<String, String> subFlowIdMap,
                                                        UmsDhjtProperties umsProperties ) {
        BusinessErrorInfoEnum.CHANNEL_REFUND_FAIL_PARAMS_ERROR.assertIsTrue(umsRefundOrderParam != null &&
                refundOrderBO != null);
        /*if(CollectionUtils.isEmpty(umsRefundOrderParam.getSubOrders())){
            umsRefundOrderParam.setSubOrders(new ArrayList<>(refundOrderBO.getSubOrders().size()));
        }*/
        refundOrderBO.getSubOrders().forEach(s->{
            final UmsRefundOrderParam.SubOrder subOrder = new UmsRefundOrderParam.SubOrder();
            subOrder.setMid(subMerchantMap.get(s.getSubOrderId()));
            subOrder.setMerOrderId(subFlowIdMap.get(s.getSubOrderId()));
            subOrder.setTotalAmount(s.getAmount() - s.getRefundPlatformDiscount());
            //umsRefundOrderParam.getSubOrders().add(subOrder);
        });
        umsRefundOrderParam.setRefundOrderId(refundOrderBO.getRefundId());
        umsRefundOrderParam.setRefundAmount(refundOrderBO.getAmount() - refundOrderBO.getRefundPlatformDiscount());

        /*BusinessErrorInfoEnum.CHANNEL_REFUND_FAIL_AMOUNT_ERROR.assertIsTrue(umsRefundOrderParam.getRefundAmount().equals(
                umsRefundOrderParam.getSubOrders().stream().mapToInt(UmsRefundOrderParam.SubOrder::getTotalAmount).sum()
        ));*/
        Result<RefundOrderResBO> result = this.doRefund(umsRefundOrderParam,umsProperties);
        if (result.getRet() != 0) {
            log.error("退款失败:{}", result);
            return result;
        }
        if (result.getData() != null && result.getData().getRefundInvoiceAmount() != null) {
            // 实际退款的金额
            PaymentRefundFlow updateRefundFlow = new PaymentRefundFlow();
            updateRefundFlow.setAmount(result.getData().getRefundInvoiceAmount());
            updateRefundFlow.setRefundChannelDiscount(umsRefundOrderParam.getRefundAmount() - result.getData().getRefundInvoiceAmount());
            QueryWrapper<PaymentRefundFlow> conditions = new QueryWrapper<>();
            conditions.eq("flow_id", umsRefundOrderParam.getRefundOrderId());
            conditions.eq("user_id", refundOrderBO.getUid());
            paymentRefundFlowMapper.update(updateRefundFlow, conditions);
            result.getData().setRefundInvoiceAmount(0);// 设置实付金额=0，不再做更新
        }
        return result;
    }



    /**
     * 整单退款
     * @param umsRefundOrderParam 退款参数
     * @return
     */
    public Result<RefundOrderResBO> refundAll(UmsDhjtRefundOrderParam umsRefundOrderParam,RefundOrderBO refundOrderBO,UmsDhjtProperties umsProperties) {
        Result<RefundOrderResBO> result = this.doRefund(umsRefundOrderParam,umsProperties);
        if (result.getRet() != 0) {
            log.error("整单退款失败:{}", result);
            return result;
        }
        if (result.getData() != null && result.getData().getRefundInvoiceAmount() != null) {
            // 实际退款的金额
            PaymentRefundFlow updateRefundFlow = new PaymentRefundFlow();
            updateRefundFlow.setAmount(result.getData().getRefundInvoiceAmount());
            updateRefundFlow.setRefundChannelDiscount(umsRefundOrderParam.getRefundAmount() - result.getData().getRefundInvoiceAmount());
            QueryWrapper<PaymentRefundFlow> conditions = new QueryWrapper<>();
            conditions.eq("flow_id", umsRefundOrderParam.getRefundOrderId());
            conditions.eq("user_id", refundOrderBO.getUid());
            paymentRefundFlowMapper.update(updateRefundFlow, conditions);
            result.getData().setRefundInvoiceAmount(0);// 设置实付金额=0，不再做更新
        }
        return result;
    }

    /**
     * 单笔子订单退款-串行
     *
     * @param umsRefundOrderParam 退款参数
     * @param subOrderBO          子订单退款参数
     * @param subMerchantMap      子商户信息
     * @param subFlowIdMap        子订单流水信息
     * @return 退款结果
     */
    private Result<RefundOrderResBO> refundOne(UmsDhjtRefundOrderParam umsRefundOrderParam, RefundOrderBO.SubOrderBO subOrderBO,
                                               Map<String, String> subMerchantMap, Map<String, String> subFlowIdMap,UmsDhjtProperties umsProperties) {
        BusinessErrorInfoEnum.CHANNEL_REFUND_FAIL_PARAMS_ERROR.assertIsTrue(umsRefundOrderParam != null &&
                subOrderBO != null);
        UmsRefundOrderParam.SubOrder subOrder = new UmsRefundOrderParam.SubOrder();
        subOrder.setMid(subMerchantMap.get(subOrderBO.getSubOrderId()));
        subOrder.setMerOrderId(subFlowIdMap.get(subOrderBO.getSubOrderId()));
        subOrder.setTotalAmount(subOrderBO.getAmount() - subOrderBO.getRefundPlatformDiscount());

        umsRefundOrderParam.setRefundOrderId(subOrderBO.getSubRefundId());
        umsRefundOrderParam.setRefundAmount(subOrder.getTotalAmount());
        //umsRefundOrderParam.setSubOrders(Collections.singletonList(subOrder));
        return this.doRefund(umsRefundOrderParam,umsProperties);
    }


    /**
     * 执行退款操作
     *
     * @param umsRefundOrderParam 退款参数
     * @return
     */
    public Result<RefundOrderResBO> doRefund(UmsDhjtRefundOrderParam umsRefundOrderParam,UmsDhjtProperties umsProperties) {
        umsRefundOrderParam.setSign(buildSignString(umsProperties.getKey(), umsRefundOrderParam));
        log.info("ums_refund_url:{}, params:{}", umsProperties.getApiUrl(), JsonUtil.toJsonString(umsRefundOrderParam));
        Result<RefundOrderResBO> result = new Result<>();
        try {
            Header[] headers = new BasicHeader[]{new BasicHeader("content-type", "application/x-www-form-urlencoded;charset=utf-8")};
            final String response = ForestHttpUtil.getInstance().doPost(umsProperties.getApiUrl(), umsRefundOrderParam, headers);

            UmsRefundOrderResult refundOrderResult = JsonUtil.fromJson(response, UmsRefundOrderResult.class);
            log.info("银联订单退款返回:{}", JsonUtil.toJsonString(refundOrderResult));

            result.setRet(UmsErrCodeEnum.SUCCESS.getCode().equalsIgnoreCase(refundOrderResult.getErrCode()) ? 0 : 1);
            result.setMsg(refundOrderResult.getErrMsg());
            if(result.getRet()==1 && DAYMAXREFUNDAMOUNT_OVER.equals(refundOrderResult.getErrCode())){
                // 超当日限额
                result.setErrorCode(BusinessErrorInfoEnum.CHANNEL_REFUND_FAIL_DAYMAXREFUNDAMOUNT_OVER.getCode());
            }
            if (refundOrderResult.getRefundInvoiceAmount() != null && refundOrderResult.getRefundInvoiceAmount() != 0
                    && !refundOrderResult.getRefundInvoiceAmount().equals(refundOrderResult.getRefundAmount())) {
                RefundOrderResBO refundOrderResBO = new RefundOrderResBO();
                // 实付部分退款金额
                refundOrderResBO.setRefundInvoiceAmount(refundOrderResult.getRefundInvoiceAmount());
                result.setData(refundOrderResBO);
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            result.setRet(1);
            result.setMsg("退款失败");
        }
        return result;
    }

    public String settleNotify(UmsDhjtSettleNotifyRequest request){

        return "SUCCESS";
    }
}
